/*
 * Copyright (C) 2010-2011 Comcast Cable.  All Rights Reserved.
 */
package com.hercules.android.receiver.handlers.commands.call;

import android.media.MediaPlayer;

import com.hercules.android.receiver.AndroidReceiver;
import com.hercules.android.receiver.handlers.commands.XREObjectCommandHandler;
import com.hercules.android.receiver.model.commands.XRECallCommand;
import com.hercules.android.receiver.model.commands.XRECommand;
import com.hercules.android.receiver.model.objects.XRESound;

/**
 * This class represents the call command handler for a XRESound object. It extends from XREObjectCommandHandler.
 * <p>
 * <b>Sample Usage:</b>
 *
 * <pre>
 * // create XRESoundCallCommandHandler instance
 * XRESoundCallCommandHandler handler = new XRESoundCallCommandHandler();
 *
 * // prepare receiver
 * AndroidReceiver receiver = prepareAggregateReceiver(new XRESound());
 *
 * // process play command to start playing
 * XRECallCommand command = prepareCommand(&quot;play&quot;);
 * handler.processCommandMessage(command, receiver);
 *
 * // process pause command to pause playing
 * command = prepareCommand(&quot;pause&quot;);
 * handler.processCommandMessage(command, receiver);
 * </pre>
 * <p>
 * <b>Thread Safety:</b> Not thread safe since it is mutable.
 *
 * @author DanLazar, orial
 * @version 1.0
 */
public class XRESoundCallCommandHandler extends XREObjectCommandHandler {
    /**
     * Represents the name of sound players.
     * <p>
     * AndroidAssembly2 changed value
     */
    private static final String SOUND_PLAYERS_NAME = "mediaPlayers";

    /**
     * Default empty constructor.
     */
    public XRESoundCallCommandHandler() {
        // empty
    }

    /**
     * Process the given command.
     *
     * @param command the command
     * @param receiver the receiver
     * @throws IllegalArgumentException if any parameter is not correct
     * @throws IllegalStateException if player is not found
     * @throws XRESoundCallCommandHandlerException if any error occurs while processing the command
     */
    @Override
    public void processCommandMessage(XRECommand command, AndroidReceiver receiver)
        throws XRESoundCallCommandHandlerException {
        String methodName = "processCommandMessage";
        Helper.logEnter(getLogger(), this, methodName, command, receiver);

        try {
            // check arguments and get target object
            XRECallCommand callCommand = Helper.checkCommand(command);
            XRESound sound = Helper.checkReceiver(receiver, callCommand, XRESound.class);

            // get command method
            String method = callCommand.getMethod();

            // execute corresponding action
            if ("play".equals(method)) {
                play(receiver, sound);
            } else if ("pause".equals(method)) {
                pause(receiver, sound);
            } else if ("setVolume".equals(method)) {
                setVolume(receiver, sound, callCommand);
            } else {
                throw new XRESoundCallCommandHandlerException("Call command method '" + method + "' is not supported.");
            }

            Helper.logExit(getLogger(), this, methodName);
        } catch (IllegalArgumentException e) {
            Helper.logError(getLogger(), e, methodName, e);
        } catch (XRESoundCallCommandHandlerException e) {
            Helper.logError(getLogger(), e, methodName, e);
        }
    }

    /**
     * This method will start playing the audio file from the beginning if audio file is not paused or resume playing
     * the audio file if audio file is paused.
     *
     * @param receiver the receiver
     * @param sound the xre sound object
     * @throws IllegalArgumentException if receiver is not correct
     * @throws IllegalStateException if player is not found
     * @throws XRESoundCallCommandHandlerException if any other error occurs
     */
    private static void play(AndroidReceiver receiver, XRESound sound) throws XRESoundCallCommandHandlerException {
        try {
            // get player
            MediaPlayer player = Helper.getMediaPlayer(receiver, SOUND_PLAYERS_NAME, sound.getId());

            // start player
            player.start();
        } catch (IllegalStateException e) {
            throw new XRESoundCallCommandHandlerException("Player is in not valid state.", e);
        }
    }

    /**
     * This method will pause the audio file.
     *
     * @param receiver the receiver
     * @param sound the xre sound object
     * @throws IllegalArgumentException if receiver is not correct
     * @throws IllegalStateException if player is not found
     * @throws XRESoundCallCommandHandlerException if any other error occurs
     */
    private static void pause(AndroidReceiver receiver, XRESound sound) throws XRESoundCallCommandHandlerException {
        try {
            // get player
            MediaPlayer player = Helper.getMediaPlayer(receiver, SOUND_PLAYERS_NAME, sound.getId());

            // pause player
            player.pause();
        } catch (IllegalStateException e) {
            throw new XRESoundCallCommandHandlerException("Player is in not valid state.", e);
        }
    }

    /**
     * This method will set volume to audio stream.
     *
     * @param receiver the receiver
     * @param sound the xre sound object
     * @param callCommand the current call command
     * @throws XRESoundCallCommandHandlerException if call command has incorrect parameters
     */
    @SuppressWarnings("boxing")
    private static void setVolume(AndroidReceiver receiver, XRESound sound, XRECallCommand callCommand)
        throws XRESoundCallCommandHandlerException {
        if (callCommand.getParams().size() == 1 && callCommand.getParams().get(0) instanceof Integer) {
            sound.setVolume((Integer) callCommand.getParams().get(0));
        } else {
            throw new XRESoundCallCommandHandlerException("Call command 'setVolume' should have one integer parameter.");
        }
        try {
            // get player
            MediaPlayer player = Helper.getMediaPlayer(receiver, SOUND_PLAYERS_NAME, sound.getId());

            // update volume
            player.setVolume(sound.getVolume(), sound.getVolume());
        } catch (IllegalStateException e) {
            throw new XRESoundCallCommandHandlerException("Player is in not valid state.", e);
        }
    }
}